package com.bscscan.dextools;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bscscan.util.NaiveSSLContext;
import com.neovisionaries.ws.client.WebSocket;
import com.neovisionaries.ws.client.WebSocketAdapter;
import com.neovisionaries.ws.client.WebSocketExtension;
import com.neovisionaries.ws.client.WebSocketFactory;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @description:
 * @author: jintengzhou
 * @date: 2021-07-21 10:36
 */
@Slf4j
@Component
public class DexToolsBootStrap implements SmartInitializingSingleton, DisposableBean {

    //    public static final String CONNECT_URL = "wss://wbs.mexc.la/raw/ws:443/";
    public static final String CONNECT_URL = "wss://ws-bsc.dextools.io:443/";

    public static final String DEXTOOLS_AUTH_PARAMS = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0IjoiVTJGc2RHVmtYMThWZWluclN4SGM2Ukh0a3dSb2VQOGUwbUlKREVyUWxQRzljWWY1T0YzN1ovQ2gyckJGVlZDdUVlVytiYkNMOWFUTThubjEyL1UzQkxmUXZRVExuNUdlNk9XOXhsQnhYTGZ3cFF2L0ltSkczcytLSFJRTDU1eFg3TEtiVU04Q1lvSjVWZ2trQ0VnLzl3PT0iLCJpYXQiOjE2MjY4NTQ0NTYsImV4cCI6MTYyNjg1NDg1Nn0.TJyMgkwYOQlnhFM4T0kEneW_yT260tkK2DBku5ZpHpo";

    WebSocket websocket = null;

    private static ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();

    @Autowired
    private DexToolsWebSocketAdapter dexToolsWebSocketAdapter;


    @SneakyThrows
    @Override
    public void afterSingletonsInstantiated() {
        start();
    }

    @Override
    public void destroy() {
        if (websocket != null) {
            websocket.disconnect();
        }
    }


    /**
     * 功能: 启动websocket
     * 作者: zjt
     * 日期: 2021/7/21 10:37
     * 版本: 1.0
     */
    public void start() throws Exception {
        try {
            WebSocketFactory factory = new WebSocketFactory();
            // Create a custom SSL context.
            // 获取一个SSLContext实例
            // Set the custom SSL context.
            factory.setSSLContext(NaiveSSLContext.getInstance("TLS"));
            factory.setVerifyHostname(false);
            websocket = factory.createSocket(CONNECT_URL);

            websocket.addHeader("Host", "ws-bsc.dextools.io");
            websocket.addHeader("Origin", "https://www.dextools.io");
            websocket.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36");

            websocket.addListener(dexToolsWebSocketAdapter);

            websocket.addExtension(WebSocketExtension.PERMESSAGE_DEFLATE);
            websocket.connect();
            log.info("连接成功 CONNECT_URL={}", CONNECT_URL);
            sendAuthConnect(websocket, DEXTOOLS_AUTH_PARAMS);
            sendSubscribePancake();

            //开启心跳
            openDexHeartBeat();
        } catch (Exception e) {
            if (websocket != null) {
                websocket.disconnect();
            }
            log.error(String.format("连接出错 CONNECT_URL=%s", CONNECT_URL), e);
        }
    }

    /**
     * 功能: 开启心跳
     * 作者: zjt
     * 日期: 2021/7/21 17:02
     * 版本: 1.0
     */
    private void openDexHeartBeat() {
        // 第二个参数为首次执行的延时时间，第三个参数为定时执行的间隔时间    
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            sendAuthConnect(websocket, DEXTOOLS_AUTH_PARAMS);
        }, 20, 20, TimeUnit.SECONDS);
    }

    /**
     * 功能: 身份验证
     * 作者: zjt
     * 日期: 2021/7/21 15:59
     * 版本: 1.0
     */
    private void sendAuthConnect(WebSocket websocket, String params) {
        final JSONObject paramMap = new JSONObject();
        paramMap.put("id", 9);
        paramMap.put("jsonrpc", "2.0");
        paramMap.put("method", "auth");
        paramMap.put("params", params);
        websocket.sendText(JSON.toJSONString(paramMap));
        log.info("发送心跳 " + JSON.toJSONString(paramMap));
    }

    /**
     * 功能: 订阅pancake
     * 作者: zjt
     * 日期: 2021/7/21 15:59
     * 版本: 1.0
     */
    private void sendSubscribePancake() {
        final JSONObject data = new JSONObject();
        data.put("id", 2);
        data.put("jsonrpc", "2.0");
        data.put("method", "subscribe");
        final JSONObject params = new JSONObject();
        params.put("channel", "bsc:pools:pancake");
        data.put("params", params);
        websocket.sendText(JSON.toJSONString(data));
        log.info("发送订阅pancake " + JSON.toJSONString(data));
    }

}